package lecture;
import downloads.Download;
import downloads.DownloadCategory;
import menus.LectureMenuItem;
import menus.MenuCategory;
import task.ExerciseSheet;
import task.TaskCategory;
import task.Task;
import news.News;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
import groups.ExerciseGroup;
import user.User;
import groups.MeetingDate;
import groups.Wish;
import hibernate.HibernateUtil;
import javax.faces.context.FacesContext;
import org.hibernate.Session;
import handingIn.HandingIn;
import handingIn.HandingInData;
import java.io.File;
import java.util.EnumMap;
import java.util.Map;
import mail.Mail;
import score.Score;
import score.ScoreData;
import staticPage.StaticPage;
import user.Rights;
import user.Role;
import user.UserAdminManagedBean;

/**
 *
 * @author Thorsten Ludwig
 */
@ManagedBean(name="lectureAdmin", eager=true )
@ApplicationScoped
public class LectureAdminManagedBean {
    
    /**
     * Die Liste aller Vorlesungen
     */
    private HashMap<String, Lecture> lectureMap;
    
    public LectureAdminManagedBean() {
        this.lectureMap = new HashMap<String,Lecture>();
        this.loadDataFromDB();
    }
    
    public void loadDataFromDB() {
        Session session = HibernateUtil.getSession();
        session.beginTransaction();
        System.out.println("Beginne laden");
        List result = session.createQuery( "from Lecture" ).list();
        for (Lecture lec : (List<Lecture>) result ) {
            this.cleanLecture(lec);
            this.addLecture(lec);
            System.out.println("Vorlesung: " + lec.getInfo().getName());            
        }
        System.out.println("Laden abgeschlossen");
        session.getTransaction().commit();
    }
    
    public void saveDataToDB() {
        System.out.println("Öffne Session");
        Session session = HibernateUtil.getSession();
        
        System.out.println("Beginne Transaktion");
        session.beginTransaction();
        for (Lecture l: this.lectureMap.values()) {
            for (MenuCategory c: l.getCategorys()) {
                for (LectureMenuItem i: c.getMenuItems()) {
                    System.out.println("Speichere Menu Items");
                    session.saveOrUpdate(i);
                }
                System.out.println("Speichere Category " + c.getName());
                session.saveOrUpdate(c);
            }
            session.saveOrUpdate(l);
        }
        session.getTransaction().commit();
        System.out.println("Lecture: Session offen:" + session.isOpen());
    }
    
    public void setUpTestData() {
        this.createTestData();
        FacesContext c = FacesContext.getCurrentInstance();
        UserAdminManagedBean ua = c.getApplication().evaluateExpressionGet(c, "#{userAdminBean}", UserAdminManagedBean.class);
        ua.createTestData();
    }
    
    public void testDBfunctionality() {
        System.out.println("Starte DB Test");
        this.createTestData();
        FacesContext c = FacesContext.getCurrentInstance();
        UserAdminManagedBean ua = c.getApplication().evaluateExpressionGet(c, "#{userAdminBean}", UserAdminManagedBean.class);
        ua.createTestData();
        System.out.println("Testdaten erstellt");
        ua.saveDataToDB();
        this.saveDataToDB();
        System.out.println("Speichern abgeschlossen");
        ua.loadDataFromDB();
        this.loadDataFromDB();
        ua.getUser("Julia").assignRole("Informatik 1 für Informatiker", Role.ADMIN);
        System.out.println("Laden abgeschlossen. Test erfolgreich");
    }
    
    public void createTestData() {
        System.out.println("doDBstuff aufgerufen");
        Lecture info1 = new Lecture("Informatik 1 für Informatiker");
        info1.getInfo().setLectureId("inf-ws11-12");
        
        UserAdminManagedBean ua = new UserAdminManagedBean();
        ua.createTestData();
        FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().put("userAdminBean", ua);
        
        User u = ua.getUser("Peter.Pan");
        info1.addUser(u);
        u.assignRole("Informatik 1 für Informatiker", Role.STUDENT);
        u = ua.getUser("Peter.Lustig");
        info1.addUser(u);
        u.assignRole("Informatik 1 für Informatiker", Role.STUDENT);
        u = ua.getUser("Peter.Paul");
        info1.addUser(u);
        u.assignRole("Informatik 1 für Informatiker", Role.STUDENT);
        u = ua.getUser("Peter.derMeter");
        info1.addUser(u);
        u.assignRole("Informatik 1 für Informatiker", Role.STUDENT);
        u = ua.getUser("Peter.Fox");
        info1.addUser(u);
        u.assignRole("Informatik 1 für Informatiker", Role.STUDENT);
        u = ua.getUser("Thorsten.Ludwig");
        info1.addUser(u);
        u.assignRole("Informatik 1 für Informatiker", Role.TUTOR);
        info1.getInfo().setRegisterByTime(true);
        info1.getInfo().setHowManyExceriseGroups(3);
        
        info1.addNews(new News("Das ist eine News", new Date(111, 12, 21)));
        info1.addNews(new News("Das ist eine weitere News", new Date(111,6,3)));
        info1.addNews(new News("Dies ist News Nummer 3", new Date(111,12,21)));
        info1.addNews(new News("Weil mir langwelig ist noch eine", new Date(111,12,22)));
        
        MeetingDate d1 = new MeetingDate(Calendar.MONDAY, 12, 15, 90);
        MeetingDate d2 = new MeetingDate(Calendar.THURSDAY, 14,30, 120);
        MeetingDate d3 = new MeetingDate(Calendar.FRIDAY,8,15,90);
        
        info1.addWeeklyDate(d1);
        info1.addWeeklyDate(d2);
        info1.addWeeklyDate(d3);
        
        ExerciseGroup g1 = new ExerciseGroup("Gruppe 1", info1, "N8");
        
        g1.addLeader("Thorsten.Ludwig",ua);
        g1.addStudent("Peter.Fox");        
        
        
        info1.getInfo().addExerciseGroup(g1);
        g1 = new ExerciseGroup("Gruppe 2", info1, "8D09");
        g1.addLeader("Thorsten.Ludwig");
        g1.addStudent("Peter.Lustig");
        info1.getInfo().addExerciseGroup(g1);
        info1.getInfo().addExerciseGroup(new ExerciseGroup("Gruppe 3", info1, "M3"));
        info1.getInfo().addExerciseGroup(new ExerciseGroup("Gruppe 4", info1, "N9"));
        info1.getInfo().addExerciseGroup(new ExerciseGroup("Gruppe 5", info1, "VBN3"));
        
        info1.getInfo().setRegistrationOpen(true);
        /*
        MenuCategory c1 = new MenuCategory("Kategorie 1");
        MenuCategory c2 = new MenuCategory("Kategorie 2");        
        MenuCategory c3 = new MenuCategory("Kategorie 3");
        
        c1.getRights().giveViewRights(Role.ADMIN);
        c2.getRights().giveViewRights(Role.ADMIN);
        c3.getRights().giveViewRights(Role.ADMIN);
        
        c1.getRights().giveViewRights(Role.STUDENT);
        c2.getRights().giveViewRights(Role.STUDENT);
        c2.getRights().giveViewRights(Role.STUDENT);
        
        LectureMenuItem m1 = new LectureMenuItem("Übungsgruppen Edit","editExerciseGroups.jsf");
        LectureMenuItem m2 = new LectureMenuItem("News","news.jsf");
        LectureMenuItem m3 = new LectureMenuItem("New Sheet","newSheet.jsf");    
        LectureMenuItem m4 = new LectureMenuItem("Edit User Role", "editUserRole.jsf");
        LectureMenuItem m5 = new LectureMenuItem("Edit Menu", "editMenu.jsf" );
        LectureMenuItem m6 = new LectureMenuItem("Punkte eintragen", "enterScore.jsf");
        LectureMenuItem m7 = new LectureMenuItem("Downloads", "editDownloads.jsf");
        LectureMenuItem m8 = new LectureMenuItem("Punkte einsehen", "viewScore.jsf");
        LectureMenuItem m9 = new LectureMenuItem("Punkte anschauen", "viewAllScore.jsf");
        LectureMenuItem m10 = new LectureMenuItem("Abgabe hochladen", "uploadHandingIn.jsf");
        LectureMenuItem m11 = new LectureMenuItem("Abgaben runterladen", "downloadHandingIns.jsf");
        LectureMenuItem m12 = new LectureMenuItem("Show Sheets", "showSheets.jsf");
        LectureMenuItem m13 = new LectureMenuItem("Statische Seiten", "editStaticPages.jsf");
        LectureMenuItem m14 = new LectureMenuItem("Test", "staticPage.jsf?staticPageName=test");
        
        LectureMenuItem m15 = new LectureMenuItem("Mails anschauen", "showMails.jsf");
        LectureMenuItem m16 = new LectureMenuItem("Mails versenden", "sendMail.jsf");
        LectureMenuItem m17 = new LectureMenuItem("Gruppen bearbeiten", "exerciseGroupAssigning.jsf");
        LectureMenuItem m18 = new LectureMenuItem("Übungsgruppen", "viewExerciseGroup.jsf");
        
        m1.getRights().giveViewRights(Role.STUDENT);
        m2.getRights().giveViewRights(Role.STUDENT);
        
        m2.getRights().giveEditRights(Role.ADMIN);
        
        m1.getRights().giveViewRights(Role.ADMIN);
        m1.getRights().giveEditRights(Role.ADMIN);
        m2.getRights().giveViewRights(Role.ADMIN);
        m3.getRights().giveViewRights(Role.ADMIN);
        m4.getRights().giveViewRights(Role.ADMIN);
        m5.getRights().giveViewRights(Role.ADMIN);
        m6.getRights().giveViewRights(Role.ADMIN);
        m7.getRights().giveViewRights(Role.ADMIN);
        
        m8.getRights().giveViewRights(Role.STUDENT);
        m9.getRights().giveViewRights(Role.ADMIN);
      
        m10.getRights().giveViewRights(Role.STUDENT);
        m11.getRights().giveViewRights(Role.ADMIN);
        m12.getRights().giveViewRights(Role.ADMIN);
        m13.getRights().giveViewRights(Role.ADMIN);
        m14.getRights().giveViewRights(Role.ADMIN);
        m14.getRights().giveEditRights(Role.ADMIN);
        
        m15.getRights().giveViewRights(Role.ADMIN);
        m16.getRights().giveViewRights(Role.ADMIN);
        m17.getRights().giveViewRights(Role.ADMIN);
        m18.getRights().giveViewRights(Role.STUDENT);
        
        c1.addItem(m1);
        c1.addItem(m2);
        c1.addItem(m3);
        c1.addItem(m4);
        c1.addItem(m5);
        c1.addItem(m6);
        c1.addItem(m7);
        c1.addItem(m8);
        c1.addItem(m9);
        c1.addItem(m10);
        c1.addItem(m11);
        c1.addItem(m12);
        c1.addItem(m13);
        c1.addItem(m14);
        c1.addItem(m18);
        
        //c2.addItem(m1);
        c2.addItem(m16);
        c2.addItem(m15);
        c2.addItem(m17);
        
        //c3.addItem(m1);
        
        info1.getInfo().addCategory(c1);
        info1.getInfo().addCategory(c2);
        info1.getInfo().addCategory(c3);

        */
        /* Info 1 pimpen */
        TaskCategory ec = this.getExerciseCategoryByName("Übungsblatt", info1);
        ec.setRequirement(60);
        ExerciseSheet sheet = new  ExerciseSheet();
        sheet.setCategory(ec);
        sheet.setName("Blatt 1");
        List<Task> list = new ArrayList<Task>();
        Task e = new Task();
        e.setName("Aufgabe 1");
        e.setMaxScore(3);
        list.add(e);
        e = new Task();
        e.setName("Aufgabe 2");
        e.setMaxScore(5);
        e.setOptional(true);
        list.add(e);
        sheet.setExercises(list);
        sheet.setDateOfRelease(new Date());
        sheet.setDateOfReturn(new Date()); 
        
        HandingIn h = new HandingIn();
        h.setHandingInDate(new Date(2011, 10, 5));
        h.setName("blub.java");
        h.setPreFixFile("bla");
        List<HandingIn> l = new ArrayList<HandingIn>();
        l.add(h);
        sheet.setHandingIns(l);
        
        info1.addSheet(sheet);
        
        this.addLecture(info1);
    }
    
    //TODO: Methode ist nur für Testdaten relevant
    private TaskCategory getExerciseCategoryByName(String name, Lecture lecture) {
        for(TaskCategory e: lecture.getExerciseCategories()) {
            if (e.getName().equals(name)) {
                return e;
            }
        }
        return null;
    }
    /**
     * 
     * @param string
     * @return 
     */
    public Lecture getLectureByName(String string) {
        Lecture tmp = this.lectureMap.get(string);
        if (tmp == null) {
            System.out.println("Gesucht ist " + string);
        }
        return tmp;
    }

    public List<Lecture> getLecturesByName(List<String> lectureNames) {
        List<Lecture> lectures = new ArrayList<Lecture>();
        for (String s: lectureNames) {
            lectures.add(getLectureByName(s));
        }
        return lectures;
    }
    
    /**
     * Vorlesung hinzufügen
     * @param lecture hinzuzufügende vorlesung
     */
    public void addLecture(Lecture lecture) {
        FacesContext c = FacesContext.getCurrentInstance();
        UserAdminManagedBean ua = c.getApplication().evaluateExpressionGet(c, "#{userAdminBean}", UserAdminManagedBean.class);
        for (User u: ua.getUsers()) {
            u.assignRole(lecture.getInfo().getName(), Role.GUEST);
        }
        this.lectureMap.put(lecture.getInfo().getName(),lecture);
        Session session = HibernateUtil.getSession();
        session.beginTransaction();
        session.saveOrUpdate(lecture);
        session.getTransaction().commit();
    }


    /**
     * Vorlesung aus der Liste streichen
     * @param lecture Die zu streichende Vorlesung
     */
    public void removeLecture(Lecture lecture) {
        this.lectureMap.remove(lecture.getInfo().getName());
    }
    
    /**
     * 
     * @return 
     */
    public List<Lecture> getLectures() {
        return new ArrayList<Lecture>(this.lectureMap.values());
    }

    public Lecture getLectureById(String string) {
        for (Lecture l: this.getLectures()) {
            if (l.getInfo().getLectureId().equals(string))
                return l;
        }
        throw new AssertionError("Vorlesungs ID nicht bekannt");
    }
    
    public List<ExerciseGroup> getUserExerciseGroupsWhereLeader(User user) {
        List<ExerciseGroup> groups = new ArrayList<ExerciseGroup>();
        for (Lecture l:getLectures()) {
            for (ExerciseGroup eg: l.getInfo().getExerciseGroups()) {
                if (eg.getLeaders().contains(user.getUsername()))
                    groups.add(eg);
            }
        }
        return groups;
    }
    
    public List<ExerciseGroup> getUserExerciseGroups(User user) {
        List<ExerciseGroup> groups = new ArrayList<ExerciseGroup>();
        for (Lecture l:getLectures()) {
            for (ExerciseGroup eg: l.getInfo().getExerciseGroups()) {
                if (eg.getStudents().contains(user.getUsername()))
                    groups.add(eg);
            }
        }
        return groups;
    }

    public List<Lecture> getLecturesByUser(User user) {
        List<Lecture> lectures = new ArrayList<Lecture>();
        for (Lecture lecture: this.getLectures()) {
            if (lecture.getInfo().getUsers().contains(user)) {
                lectures.add(lecture);
            }
        }
        return lectures;
    }

    private void cleanLecture(Lecture lec) {
        lec.getInfo().setExerciseGroups(new ArrayList<ExerciseGroup>(lec.getInfo().getExerciseGroups()));
        FacesContext c = FacesContext.getCurrentInstance();
        UserAdminManagedBean ua = c.getApplication().evaluateExpressionGet(c, "#{userAdminBean}", UserAdminManagedBean.class);        
        List<User> users = new ArrayList<User>();
        for (User u: lec.getInfo().getUsers()) {
            users.add(ua.getUser(u.getUsername()));
        }
        lec.getInfo().setUsers(users);
        lec.setWishes(new HashMap<String, Wish>(lec.getWishes()));
        lec.setNews(new ArrayList<News>(lec.getNews()));
        lec.setExerciseCategories(new ArrayList<TaskCategory>(lec.getExerciseCategories()));
        lec.setExerciseSheets(new ArrayList<ExerciseSheet>(lec.getExerciseSheets()));
        lec.setTimes(new ArrayList<MeetingDate>(lec.getTimes()));
        lec.setDownloads(new ArrayList<DownloadCategory>(lec.getDownloads()));
        lec.setScore(new HashMap<ExerciseSheet, ScoreData>(lec.getScore()));
        lec.setHandingIns(new HashMap<ExerciseSheet, HandingInData>(lec.getHandingIns()));
        lec.setMails(new ArrayList<Mail>(lec.getMails()));
        lec.setStaticPages(new ArrayList<StaticPage>(lec.getStaticPages()));
        lec.setMenuItems(new ArrayList<LectureMenuItem>(lec.getMenuItems()));
        lec.setCategorys(new ArrayList<MenuCategory>(lec.getCategorys()));
        
        for (ExerciseGroup eg: lec.getInfo().getExerciseGroups()) {
            eg.setLeaders(new ArrayList<String>(eg.getLeaders()));
            eg.setStudents(new ArrayList<String>(eg.getStudents()));
        }
        for (ExerciseSheet sheet:lec.getExerciseSheets()) {
            sheet.setHandingIns(new ArrayList<HandingIn>(sheet.getHandingIns()));
            sheet.setExercises(new ArrayList<Task>(sheet.getExercises()));
        }
        for(DownloadCategory dc:lec.getDownloads()) {
            dc.setDownloads(new ArrayList<Download>(dc.getDownloads()));
        }
        
        for (ExerciseSheet sheet:lec.getScore().keySet()) {
            //Map<String, List <Score>>
            ScoreData sd=lec.getScore().get(sheet);    
            for (String s: sd.getField().keySet()) {
                sd.getField().put(s, new ArrayList<Score>(sd.getField().get(s)));
            }
            sd.setField(new HashMap<String,List<Score>>(sd.getField()));
        }
        
        for (ExerciseSheet sheet: lec.getHandingIns().keySet()) {
            HandingInData hd = lec.getHandingIns().get(sheet);
            //Map<String, Map<HandingIn, File>>
            for (String s: hd.getField().keySet()) {
                hd.getField().put(s, new HashMap<HandingIn, File>(hd.getField().get(s)));
            }
            hd.setField(new HashMap<String,Map<HandingIn,File>> (hd.getField()));
        }
        for (LectureMenuItem l:lec.getMenuItems()) {
            Rights r = l.getRights();
            r.setHasEditRights(new EnumMap<Role,Boolean>(r.getHasEditRights()));
            r.setHasViewRights(new EnumMap<Role,Boolean>(r.getHasViewRights()));
        }
        
        for (MenuCategory m:lec.getCategorys()) {
            Rights r = m.getRights();
            r.setHasEditRights(new EnumMap<Role,Boolean>(r.getHasEditRights()));
            r.setHasViewRights(new EnumMap<Role,Boolean>(r.getHasViewRights()));
            m.setMenuItems(new ArrayList<LectureMenuItem>(m.getMenuItems()));
        }
    }
    
}
